#ifndef __BASIC_EP_H__
#define __BASIC_EP_H__

#include <basic/sock.h>

__BEGIN_DECLS

#define EP_POLL_MAX_NUM         1024

struct _ep;
typedef struct _ep *EP;
struct _ep_slot;
typedef struct _ep_slot *EP_SLOT;

/*
 * 事件环境初始
 */
extern int  /* 0:成功 -1:失败 */
ep_init();

/*
 * 事件环境清理
 */
extern int  /* 0:成功 -1:失败 */
ep_clean();

/*
 * 创建接口
 */
extern int  /* 0:成功 */
ep_create(
        EP *epp                 /* [OUT] 接口 */
        );

/*
 * 释放接口句柄
 */
extern int  /* 0:成功 */
ep_free(
        EP ep                   /* [IN] 接口 */
        );

/*
 * 向接口登记通信槽
 */
extern int  /* 0:成功 */
ep_slot_register(
        EP ep,              /* [IN] 接口 */
        SOCKET new_sock,    /* [IN] 新增套接字 */
        unsigned int is_listen,    /* [IN] 是否监听 */
        EP_SLOT *ep_slot    /* [OUT] 通信槽 */
);

/*
 * 设置通信槽属性:消息头
 */
extern int  /* 0:成功 */
ep_slot_set_wrap(
        EP_SLOT ep_slot     /* [IN] 通信槽 */
        );

/*
 * 设置通信槽属性:超时
 */
extern int  /* 0:成功 */
ep_slot_set_timeout(
        EP_SLOT ep_slot,    /* [IN] 通信槽 */
        int timeout         /* [IN] 超时秒数 <=0:无超时 */
        );

/*
 * 从接口注销通信槽
 */
extern int  /* 0:成功 -1:通信槽未使用 */
ep_slot_revoke(
        EP ep,              /* [IN] 接口 */
        EP_SLOT ep_slot     /* [IN] 通信槽 */
);

/*
 * 轮询通信槽
 */
struct ep_active_slot
{/*{{{*/
    enum
    {
        EP_SLOT_CONN,
        EP_SLOT_READ,
        EP_SLOT_ABORT,
        EP_SLOT_TIMEOUT
    } type; 
    union   
    {
        struct ep_active_slot_conn
        {
            SOCKET sock;
        } _conn;
        struct ep_active_slot_read
        {
            char *msg;
            int msg_size;
            unsigned short check;
        } _read;
        struct ep_active_slot_abort
        {
            SOCKET sock;
            int error;
        } _abort;
        struct ep_active_slot_timeout
        {
            SOCKET sock;
        } _timeout;
    } _u;
    EP_SLOT slot;
    int slot_idx;
    unsigned int seq;
    struct ep_active_slot *next;
};/*}}}*/

extern int  /* 0:成功 -1:轮询系统调用出错 */
ep_poll(
	EP ep,              /* [IN] 接口 */
	struct ep_active_slot **active_list /* [OUT] 活跃通信槽 */
);

#define EP_ACTIVE_LIST_NEXT(_active)                            \
do                                                              \
{                                                               \
    if(_active)                                                 \
    {                                                           \
        struct ep_active_slot *_tmp=_active;                    \
        _active=_active->next;                                  \
        if(_tmp->type == EP_SLOT_READ)                          \
            free(_tmp->_u._read.msg);                           \
        free(_tmp);                                             \
    }                                                           \
} while(0)

#define EP_ACTIVE_LIST_FREE(_active)                            \
while(_active)                                                  \
    EP_ACTIVE_LIST_NEXT(_active)

/*
 * 向通信槽写入消息
 */
extern int  /* 0:成功 -1:监听通信槽 -2:消息长度错误 -3:校验值不一致
               -4:recv出错 */
ep_write(
	EP ep,                  /* [IN] 接口 */
    EP_SLOT ep_slot,        /* [IN] 通信槽号 */
	char *msg,              /* [IN] 消息缓冲区 */
	int *msg_size           /* [IN,OUT] 消息大小 */
);

/*
 * 接口信息
 */
struct ep_info
{/*{{{*/
    int slot_num;
    int used_slot_num;
};/*}}}*/
int ep_get_info(    /* 0:成功 */
        EP ep,                  /* [IN] 接口 */
        struct ep_info *info    /* [OUT] 接口信息 */
        );

/*
 * 通信槽信息
 */
struct ep_slot_info
{/*{{{*/
    SOCKET sock;
    int slot_idx;
    unsigned int is_listen;
    unsigned int is_wrap;
    struct sock_info sock_info;
//    USHORT check;
    unsigned int seq;
};/*}}}*/
int ep_get_slot_info(    /* 0:成功 */
        EP ep,                  /* [IN] 接口 */
        EP_SLOT ep_slot,        /* [IN] 通信槽 */
        struct ep_slot_info *slot_info   /* [OUT] 通信槽信息 */
        );

/***********************************************/

#if 0
struct _epx;
typedef struct _epx *EPX;
#define _epx_slot _ep_slot
typedef struct _epx_slot *EPX_SLOT;
struct _epx_thrd;
typedef struct _epx_thrd *EPX_THRD;

extern int epx_init();

extern int epx_clean();

extern int epx_create(unsigned int is_multi_thread, EPX *epxp);

extern int epx_free(EPX epx);

/*
 * 创建线程数据
 */
extern int epx_thrd_create(EPX epx, EPX_THRD *p_epx_thrd);

extern int epx_slot_create(SOCKET sock, unsigned int is_listen,
        EPX_SLOT *p_epx_slot);

extern int epx_slot_set_wrap(EPX_SLOT epx_slot);

extern int epx_slot_set_timeout(EPX_SLOT epx_slot, int timeout);

extern int epx_slot_register(EPX epx, EPX_SLOT epx_slot);

extern int epx_slot_revoke(EPX epx, EPX_SLOT slot);

extern int epx_poll(EPX epx, EPX_THRD epx_thrd,
        struct ep_active_slot **active_list);

//extern int epx_write();
#endif

__END_DECLS

#endif
